const express = require('express');
const app = express();
const fs = require('fs');
const jwt = require('jsonwebtoken');
const { expressjwt } = require("express-jwt");
const CryptoJS = require("crypto-js");

let secret = 'Y%BG9GjXU:p^FaW~';

app.use(express.static('.'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.get('/', async function (req, res) {
    let html = await fs.promises.readFile(__dirname + '/index.html', { encoding: 'utf8' });
    res.send(html);
});

app.post('/generate', async function (req, res) {
    let token = jwt.sign({
        data: 'foobar'
    }, secret, { expiresIn: 10 });

    // console.log(token);

    res.json({
        status: true,
        token: token,
    });
});

app.post('/api_one', async function (req, res) {
    let token = req.body.token;
    try {
        let decoded = jwt.verify(token, secret);
        res.json({
            status: true,
            msg: 'ok',
            decoded: decoded,
        });
        return;
    } catch (err) {
        // console.log(err);
        res.json({
            status: false,
            msg: err.toString(),
            decoded: {},
        });
        return;
    }
});

// function getToken(req) {
//     if (req.headers.authorization && req.headers.authorization.split(" ")[0] === "Bearer") {
//         return req.headers.authorization.split(" ")[1];
//     } else if (req.query && req.query.token) {
//         return req.query.token;
//     }
//     return null;
// }

function getToken(req) {
    if (req.headers.authorization && req.headers.authorization.split(" ")[0] === "Bearer") {
        return CryptoJS.AES.decrypt(req.headers.authorization.split(" ")[1], secret).toString(CryptoJS.enc.Utf8);
    } else if (req.query && req.query.token) {
        return CryptoJS.AES.decrypt(req.query.token, secret).toString(CryptoJS.enc.Utf8);
    }
    return null;
}

app.post('/api_two', expressjwt({ secret: secret, algorithms: ["HS256"], getToken: getToken }), async function (req, res) {

    res.json({
        status: true,
        msg: 'ok',
        decoded: req.auth,
    });
});


function VERIFY(token) {
    if (!token) return false;

    try {
        token = CryptoJS.AES.decrypt(token, secret).toString(CryptoJS.enc.Utf8);
        if (!token) return false;

        let result = JSON.parse(token);
        if (!result._RAND_ || !result._TIME_ || !result._SIGN_) return false;

        let rand = String(result._RAND_);
        let time = parseInt(result._TIME_) || 0;
        let sign = String(result._SIGN_);

        let now = parseInt(new Date().getTime() / 1000);
        if (now - time > 600) {
            return false;
        }
        if (CryptoJS.MD5('' + rand + time + secret).toString().toUpperCase() != sign) {
            return false;
        }
        return true;
    } catch (err) {
        console.log(err);
        return false;
    }
}

function verifyMiddleware(req, res, next) {
    if (!VERIFY(req.body._VERIFY_)) {
        res.json({
            status: false,
            msg: 'fail',
        });
        return;
    }
    next();
}

app.post('/api_three', verifyMiddleware, async function (req, res) {
    console.log(req.body);

    res.json({
        status: VERIFY(req.body._VERIFY_),
        msg: 'ok',
    });
});

app.use('/r1', require('./r1.js'));
app.use('/r2', require('./r2.js'));

app.use(function (err, req, res, next) {
    if (err.name === "UnauthorizedError") {
        res.status(401).send("invalid token...");
    } else {
        next(err);
    }
});

app.listen(3000);
